
#include <QSettings>
#include <QCompleter>
#include <QDateTime>
#include <QThread>
#include <QDir>
#include <QTimer>
#include <QScrollBar>
#include <QFileDialog>
#include <QFile>
#include "imagelist.h"
#include "log.h"
#include "requestmanager.h"
#include "components/board.h"
#include "components/chan.h"
#include "imagestorage.h"
#include <boost/bind.hpp>

using namespace Wishmaster;
extern Wishmaster::ImageStorage* g_imagestorage;

class RefresherThread : public QThread
{
public:
	RefresherThread(ImageList* parent = 0) : QThread(parent),
		m_list(parent)
	{
	}

	virtual void run()
	{
		m_list->refreshLists();
	}

private:
	ImageList* m_list;
};

namespace Wishmaster
{
	ImageFetchThread::ImageFetchThread(Wishmaster2::Network::RequestManager* requestManager, bool saveInDb, const ThreadPtr& thread, QString host, QObject* parent) : QThread(parent),
		m_saveInDb(saveInDb), m_thread(thread), m_host(host), m_requestManager(requestManager)
	{

	}

	ImageFetchThread::~ImageFetchThread()
	{
		log(llDebug, "ImageFetchThread::~ImageFetchThread()");
	}

	void ImageFetchThread::setPiclinks(QStringList piclinks)
	{
		m_piclinks = piclinks;
	}

	void ImageFetchThread::setIconList(QList<PostIcon> icons)
	{
		m_icons = icons;
	}

	void ImageFetchThread::setTags(QStringList tags)
	{
		m_tags = tags;
	}

	void ImageFetchThread::setPath(const QString& path)
	{
		m_path = path;
	}

	void ImageFetchThread::run()
	{
		log(llDebug, "ImageFetchThread started");
		m_totalPics = 0;
		m_donePics = 0;
		foreach(const PostIcon& icon, m_icons)
		{
			m_totalPics++;
			if(!icon.local)
			{
				log(llDebug, "Fetching picture from server: %s", qPrintable(icon.piclink));
				Wishmaster2::Network::Url url(icon.piclink.toStdString());
				if(url.host().empty())
					url.setHost(m_host.toStdString());
				if(url.scheme().empty())
					url.setScheme("http");
				Wishmaster2::Network::RequestPtr request = m_requestManager->createRequest(url);
				request->connectSignalFinished(boost::bind(&ImageFetchThread::requestFinished, this, _1));
				m_requests[request->id()] = request;
				m_requestManager->enqueueRequest(request);
			}
			else
			{
				PostPtr post = m_thread->lookupPost(icon.postId);
				if(!post)
				{
					log(llDebug, "No post: %s", qPrintable(icon.postId.toString()));
					m_donePics++;
					continue;
				}
				QString fname = post->attachment(icon.attachNumber)->filename();
				if(m_saveInDb)
				{
					int id;
					if(icon.piclink.endsWith(".gif"))
						id = g_imagestorage->addImage(post->attachment(icon.attachNumber)->data(), m_path, fname);
					else
						id = g_imagestorage->addImage(post->attachment(icon.attachNumber)->image(), m_path, fname);
					if(id)
					{
						foreach(QString tag, m_tags)
						{
							g_imagestorage->addTagForID(id, tag);
						}
					}
				}
				else
				{
					QFile file(m_path + QDir::separator() + fname);
					file.open(QIODevice::WriteOnly);
					file.write(post->attachment(icon.attachNumber)->data());
					file.close();
				}
				m_donePics++;
				emit progress(m_donePics, m_totalPics);
			}
		}
		QThread::exec();
	}

	void ImageFetchThread::requestFinished(int requestId)
	{
		m_donePics++;

		auto it = m_requests.find(requestId);
		if(it == m_requests.end())
			return;
		Wishmaster2::Network::RequestPtr request = it->second;

		QString path = QString::fromStdString(request->url().path());
		QString fname = path.mid(path.lastIndexOf('/') + 1);
		log(llDebug, "ImageFetchThread::requestFinished: %s", qPrintable(fname));
		QByteArray arr(request->content()->data(), request->content()->size());
		if(m_saveInDb)
		{
			int id;
			if(fname.endsWith(".gif"))
			{
				id = g_imagestorage->addImage(arr, m_path, fname);
			}
			else
			{
				QImage image;
				image.loadFromData(arr);
				id = g_imagestorage->addImage(image, m_path, fname);
			}
			if(id)
			{
				foreach(QString tag, m_tags)
				{
					g_imagestorage->addTagForID(id, tag);
				}
			}
		}
		else
		{
			QFile file(m_path + QDir::separator() + fname);
			file.open(QIODevice::WriteOnly);
			file.write(arr);
			file.close();
		}
		log(llDebug, "Fetched: %s", qPrintable(m_path + fname));
		emit progress(m_donePics, m_totalPics);
		if(m_donePics >= m_totalPics)
			exit(0);
	}
}

ImageListItem::ImageListItem(QListWidget* parent) : QListWidgetItem(parent, ImageListItemType)
{
}

ImageListItem::~ImageListItem()
{
}

void ImageListItem::setPiclink(const QString& pic)
{
	m_piclink = pic;
}

QString ImageListItem::piclink()
{
	return m_piclink;
}

void ImageListItem::setAttachmentIndex(int index)
{
	m_attachmentIndex = index;
}

int ImageListItem::attachmentIndex() const
{
	return m_attachmentIndex;
}

void ImageListItem::setPostId(const Wishmaster::PostId& id)
{
	m_postId = id;
}

Wishmaster::PostId ImageListItem::postId() const
{
	return m_postId;
}


ImageList::ImageList(Wishmaster2::Network::RequestManager* requestManager, QWidget* parent) : QDialog(parent),
	m_ui(new Ui::ImageList),
	m_requestManager(requestManager)
{
	m_ui->setupUi(this);
	m_ui->pb_loading->setVisible(false);
	QSettings settings;
	QStringList tags = settings.value("imageview/tags").toStringList();
	QCompleter* completer = new QCompleter(tags);
	m_ui->e_tag->setCompleter(completer);
	m_ui->lw_fut->addItems(tags);
}

ImageList::~ImageList()
{
}

QStringList ImageList::piclinks(const QString& host)
{
	QStringList piclinks;
	for(int i = 0; i < m_ui->lw_added->count(); i++)
	{
		ImageListItem* item = static_cast<ImageListItem*>(m_ui->lw_added->item(i));
		QString link;
		if(item->piclink().startsWith('/'))
			link = QString("http://") + host + item->piclink();
		else
			link = item->piclink();
		piclinks.append(link);

	}
	return piclinks;
}

QList<Wishmaster::PostIcon> ImageList::icons()
{
	QList<Wishmaster::PostIcon> list;
	for(int i = 0; i < m_ui->lw_added->count(); i++)
	{
		ImageListItem* it = static_cast<ImageListItem*>(m_ui->lw_added->item(i));
		Wishmaster::PostIcon icon;
		icon.piclink = it->piclink();
		icon.postId = it->postId();
		icon.attachNumber = it->attachmentIndex();
		icon.local = false;
		list.append(icon);
	}
	return list;
}

void ImageList::save()
{
	QString host = m_thread->parent()->getParent()->getHost();
	ImageFetchThread* thread = new ImageFetchThread(m_requestManager, true, m_thread, host);
	connect(thread, SIGNAL(progress(int, int)), this, SLOT(progress(int, int)));
	thread->setPath(QString("db/pics") + QDir::separator() + host +
			QDir::separator() + m_thread->parent()->name() + QDir::separator() +
			m_thread->id().threadStringId() + QDir::separator());
	thread->setPiclinks(piclinks(host));
	thread->setIconList(icons());

	QStringList tags;
	for(int i = 0; i < m_ui->lw_tags->count(); i++)
	{
		tags.append(m_ui->lw_tags->item(i)->text());
	}
	thread->setTags(tags);
	thread->start();
	m_ui->lw_added->clear();
	m_ui->pb_loading->setVisible(true);
}

void ImageList::saveAsFile()
{
	QString dir = QFileDialog::getExistingDirectory();
	if(!dir.isNull())
	{
		QString host = m_thread->parent()->getParent()->getHost();
		ImageFetchThread* thread = new ImageFetchThread(m_requestManager, false, m_thread, host);
		connect(thread, SIGNAL(progress(int, int)), this, SLOT(progress(int, int)));
		thread->setPath(dir);
		thread->setPiclinks(piclinks(host));
		thread->setIconList(icons());
		thread->start();
		m_ui->lw_added->clear();
		m_ui->pb_loading->setVisible(true);
	}
}

void ImageList::setThread(Wishmaster::ThreadPtr thread)
{
	m_thread = thread;
	QThread* refresher = new RefresherThread(this);
	connect(refresher, SIGNAL(finished()), this, SLOT(refreshThreadDone()));
	refresher->start();
}

void ImageList::refreshLists()
{
	m_icons.clear();
	for(int postNumber = 0; postNumber < m_thread->getActualPostsCount(); postNumber++)
	{
		PostPtr post = m_thread->getPost(postNumber);
		for(int i = 0; i < post->attachmentCount(); i++)
		{
			if(post->attachment(i)->type().startsWith("image"))
			{
				QImage thumb = post->attachment(i)->thumbnail();
				if(!thumb.isNull())
				{
					Wishmaster::PostIcon icon;
					icon.postId = post->id();
					icon.image = thumb.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
					icon.piclink = post->attachment(i)->url().toString();
					icon.local = post->attachment(i)->hasData();
					log(llDebug, "image: %s, local: %d [%s]", qPrintable(icon.piclink), icon.local, qPrintable(post->id().toString()));
					icon.attachNumber = i;
					m_icons.append(icon);
				}
			}
		}
	}
}

void ImageList::refreshThreadDone()
{
	m_ui->lw_images->clear();
	foreach(PostIcon icon, m_icons)
	{
		ImageListItem* item = new ImageListItem(m_ui->lw_images);
		item->setIcon(QIcon(QPixmap::fromImage(icon.image)));
		item->setSizeHint(QSize(200, 200));
		item->setPiclink(icon.piclink);
		item->setPostId(icon.postId);
		item->setAttachmentIndex(icon.attachNumber);
	}
}

void ImageList::progress(int done, int total)
{
	m_ui->pb_loading->setValue(done * 100.0 / total);
	if(done == total)
		m_ui->pb_loading->setVisible(false);
	else if(!m_ui->pb_loading->isVisible())
		m_ui->pb_loading->setVisible(true);
}

void ImageList::itemAdd(QListWidgetItem* item)
{
	if(item->type() != ImageListItem::ImageListItemType)
		return;

	int scrollValue = m_ui->lw_images->verticalScrollBar()->value();
	ImageListItem* it = static_cast<ImageListItem*>(item);
	QIcon icon = item->icon();
	ImageListItem* newitem = new ImageListItem(m_ui->lw_added);
	newitem->setIcon(icon);
	newitem->setPiclink(it->piclink());
	newitem->setSizeHint(QSize(200, 200));
	newitem->setPostId(it->postId());
	newitem->setAttachmentIndex(it->attachmentIndex());
	delete it;
	m_ui->lw_images->verticalScrollBar()->setValue(scrollValue);
}

void ImageList::itemRemove(QListWidgetItem* item)
{
	if(item->type() != ImageListItem::ImageListItemType)
		return;

	ImageListItem* it = static_cast<ImageListItem*>(item);
	QIcon icon = item->icon();
	ImageListItem* newitem = new ImageListItem(m_ui->lw_images);
	newitem->setIcon(icon);
	newitem->setPiclink(it->piclink());
	newitem->setSizeHint(QSize(200, 200));
	delete it;
}

void ImageList::addTag()
{
	QString tag = m_ui->e_tag->text();
	log(llDebug, "tag: %s", qPrintable(tag));
	if(tag.isEmpty())
		return;
	m_ui->lw_tags->addItem(tag);
	QTimer::singleShot(10, this, SLOT(emptyTagLine()));
}

void ImageList::tagChanged(const QString& tag)
{
	if(tag.isEmpty())
		m_ui->b_addTag->setEnabled(false);
	else if(!m_ui->b_addTag->isEnabled())
		m_ui->b_addTag->setEnabled(true);
}

void ImageList::addFut(QListWidgetItem* item)
{
	m_ui->lw_tags->addItem(item->text());
	delete item;
	m_ui->lw_fut->selectionModel()->clearSelection();
}

void ImageList::emptyTagLine()
{
	m_ui->e_tag->clear();
}

void ImageList::addAll()
{
	for(int i = 0; i < m_ui->lw_images->count(); i++)
	{
		ImageListItem* it = static_cast<ImageListItem*>(m_ui->lw_images->item(i));
		ImageListItem* newitem = new ImageListItem(m_ui->lw_added);
		newitem->setIcon(it->icon());
		newitem->setPiclink(it->piclink());
		newitem->setSizeHint(QSize(200, 200));
	}
	m_ui->lw_images->clear();
}

void ImageList::removeAll()
{
	for(int i = 0; i < m_ui->lw_added->count(); i++)
	{
		ImageListItem* it = static_cast<ImageListItem*>(m_ui->lw_added->item(i));
		ImageListItem* newitem = new ImageListItem(m_ui->lw_images);
		newitem->setIcon(it->icon());
		newitem->setPiclink(it->piclink());
		newitem->setSizeHint(QSize(200, 200));
	}
	m_ui->lw_added->clear();
}
